#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include "commtraff.h"

#ifdef USE_PRINTF_DUMPINFO
#include <stdio.h>
#define PRINT_INFO(...) printf(__VA_ARGS__)
#define PRINT_ERROR(...) printf(__VA_ARGS__)
#else
#include "commtraff_hilog.h"
#define PRINT_INFO(...) LOGI(__VA_ARGS__)
#define PRINT_ERROR(...) LOGE(__VA_ARGS__)
#endif

// Convert timestamp to readable string format (seconds precision)
static const char* FormatTimestamp(time_t timestamp) {
    static char timeStr[32];
    struct tm *tm_info = localtime(&timestamp);
    
    if (tm_info != NULL) {
        strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm_info);
    } else {
        snprintf(timeStr, sizeof(timeStr), "Invalid_Time");
    }
    
    return timeStr;
}

// Print session layer data
static void PrintSessionTraff(const SessionTraff *session) {
    const char *session_types[] = {
            "INNER_SESSION", "BYTE_SESSION", "MESSAGE_SESSION", "STREAM_SESSION", "FILE_SESSION"
    };
    PRINT_INFO("[SESSION] LocalName=%s PeerName=%s UdidHash=%s PID=%u Time=%s Handle=%d ChannelID=%u ConnID=%u SessionID=%u Type=%s SendBytes=%u RecvBytes=%u\n",
         session->localSessionName, session->peerSessionName, session->peerUdidHash,
         session->pid, FormatTimestamp(session->time), session->handle, session->channelId,
         session->connId, session->sessionId, session_types[session->sessionType],
         session->sendBytes, session->recvBytes);
}

// Print transport layer data
static void PrintTransportTraff(const TransportTraff *transport) {
    PRINT_INFO("[TRANSPORT] Interface=%s SrcMAC=%s DstMAC=%s PID=%u Time=%s SocketID=%u Protocol=%u SendBytes=%" PRIu64 " SendPacks=%" PRIu64 " RecvBytes=%" PRIu64 " RecvPacks=%" PRIu64 "\n",
         transport->ifName, transport->local, transport->remote, transport->pid, FormatTimestamp(transport->time), transport->sockId, transport->protocol,
         transport->sendBytes, transport->sendPacks, 
         transport->recvBytes, transport->recvPacks);
}

// Print link layer data
static void PrintLinkTraff(const LinkTraff *link) {
    PRINT_INFO("[LINK] Interface=%s Time=%s TxBytes=%" PRIu64 " TxPacks=%" PRIu64 " RxBytes=%" PRIu64 " RxPacks=%" PRIu64 " RxErrors=%" PRIu64 " TxErrors=%" PRIu64 " RxDropped=%" PRIu64 " TxDropped=%" PRIu64 "\n",
         link->ifName, FormatTimestamp(link->time), link->txBytes, link->txPackets,
         link->rxBytes, link->rxPackets, link->rxErrPackets,
         link->txErrPackets, link->rxDropPackets, link->txDropPackets);
}

// Print RPC layer data
static void PrintRpcTraff(const RpcTraff *rpc) {
    PRINT_INFO("[RPC] ProxyHandle=%d StubHandle=%d SendLen=%d RecvLen=%d RecvSeq=%" PRIu64 " SendSeq=%" PRIu64 " LocalPid=%d LocalUid=%d PeerPid=%d PeerUid=%d Time=%s\n",
         rpc->proxyHandle, rpc->stubHandle, rpc->sendDataLen,
         rpc->recvDataLen, rpc->recvDataSeq, rpc->sendDataSeq, 
         rpc->localpid, rpc->localuid, rpc->peerpid, rpc->peeruid, FormatTimestamp(rpc->time));
}

static void PrintWpaTraff(const WpaTraff *wpa) {
    PRINT_INFO("[WPA] Interface=%s Signal=%d Noise=%d SNR=%u TxRate=%u RxRate=%u RealTxRate=%u RealRxRate=%u TxEfficiency=%u Frequency=%u TxPackets=%u RxPackets=%u ChLoad=%u TxBytes=%" PRIu64 " RxBytes=%" PRIu64 " TxFailed=%u TxRetries=%u Time=%s\n",
             wpa->ifName, wpa->signal, wpa->noise, wpa->snr, wpa->txrate, wpa->rxrate,
             wpa->realTxrate, wpa->realRxrate, wpa->txEfficiency, wpa->frequency,
             wpa->txPackets, wpa->rxPackets, wpa->chload, 
             wpa->txBytes, wpa->rxBytes,
             wpa->txFailed, wpa->txRetries, FormatTimestamp(wpa->time));
}

// Print hisysevent data
static void PrintHisyseventData(const HisyseventData *hisysevent) {
    PRINT_INFO("[HISYSEVENT] Domain=%s Event=%s Field=%s Value=%" PRIu64 " Time=%s\n",
             hisysevent->domain, hisysevent->event, hisysevent->field, 
             hisysevent->value, FormatTimestamp(hisysevent->time));
}

// Print all CommTraff fields
void CommTraffInfoPrint(const CommTraff *traff)
 {
    if (traff == NULL) {
        PRINT_ERROR("CommTraff pointer is NULL\n");
        return;
    }

    switch (traff->traffType) {
        case LINK_LAYER_DATA:
            PrintLinkTraff(&traff->data.linkTraff);
            break;
        case TRANSPORT_LAYER_DATA:
            PrintTransportTraff(&traff->data.transportTraff);
            break;
        case SESSION_LAYER_DATA:
            PrintSessionTraff(&traff->data.sessionTraff);
            break;
        case RPC_LAYER_DATA:
            PrintRpcTraff(&traff->data.rpcTraff);
            break;
        case WPA_LAYER_DATA: // Added case for WPA traffic
            PrintWpaTraff(&traff->data.wpaTraff);
            break;
        case HISYSEVENT_DATA:
            PrintHisyseventData(&traff->data.hisyseventData);
            break;
        default:
            PRINT_ERROR("Unknown traffic type: %d\n", traff->traffType);
            break;
    }
}